#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    setupDir(); //populates technique list as well
    setupActions();
    setupTable();
    setupUi();

    mediaObject = new Phonon::MediaObject(this);
    audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);

    connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
            this, SLOT(stateChanged(Phonon::State,Phonon::State)));

    Phonon::createPath(mediaObject, audioOutput);

    currentTechIndex = 0;
    mediaObject->setCurrentSource(Phonon::MediaSource(techniqueList[currentTechIndex]));

    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(timeOut()));

    wasPosition = false;
}

MainWindow::~MainWindow()
{
}

void MainWindow::setupDir()
{
    //initialize data
    QDir dir;
    //sets directory path for audio files
    if(!dir.cd("audio/"))
    {
        qDebug() << "path does not exist";
        exit(1);
    }

    QDirIterator it(dir.path(), QDir::Files|QDir::NoSymLinks, QDirIterator::Subdirectories);
    QList<QString> tmpList;

    while(it.hasNext())
    {
        it.next();

        qDebug() << "loading audio file: " << it.filePath();
        //if current iteration is a file(not dir), store path in posVector
        if(it.fileInfo().isFile())
        {
            if(!it.fileName().contains("p_"))
                tmpList.push_back(it.filePath());
        }
    }

    int tmpSize = tmpList.size();
    srand(time(NULL));
    for(int i = 0; i < tmpSize; ++i)
    {
        int x = rand() % tmpList.size();
        techniqueList.push_back(tmpList[x]);
        tmpList.removeAt(x);
    }
}

void MainWindow::setupActions()
{
    playAction = new QAction(style()->standardIcon(QStyle::SP_MediaPlay), tr("Play"), this);
    playAction->setShortcut(tr("Ctrl+P"));
    pauseAction = new QAction(style()->standardIcon(QStyle::SP_MediaPause), tr("Pause Training"), this);
    pauseAction->setShortcut(tr("Ctrl+A"));
    pauseAction->setDisabled(true);
    nextAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipForward), tr("Next"), this);
    nextAction->setShortcut(tr("Ctrl+N"));
    previousAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipBackward), tr("Previous"), this);
    previousAction->setShortcut(tr("Ctrl+R"));

    connect(playAction, SIGNAL(triggered()), this, SLOT(play()));
    connect(pauseAction, SIGNAL(triggered()), this, SLOT(stop()));
    connect(nextAction, SIGNAL(triggered()), this, SLOT(next()));
    connect(previousAction, SIGNAL(triggered()), this, SLOT(previous()));
}

void MainWindow::setupTable()
{
    QStringList headers;
    headers << tr("Technique");

    table = new QTableWidget(0, 1);
    table->setHorizontalHeaderLabels(headers);
    int j = 0;
    for(int i = 0; i < techniqueList.size(); ++i)
    {
        QString tmpStr = techniqueList[i].section('/', -1).section('.', 0,0);
        if(!tmpStr.contains("p_"))
        {
            tableItem = new QTableWidgetItem(tmpStr);
            tableItem->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
            table->insertRow(j);
            table->setItem(j, 0, tableItem);
            ++j;
        }
    }
    table->resizeColumnsToContents();
}

void MainWindow::setupUi()
{
    QToolBar *bar = new QToolBar;

    bar->addAction(previousAction);
    bar->addSeparator();
    bar->addAction(playAction);
    bar->addAction(pauseAction);
    bar->addSeparator();
    bar->addAction(nextAction);

    viewVideo = new QPushButton("View Video");
    connect(viewVideo, SIGNAL(clicked()), this, SLOT(viewVideoClicked()));

    viewPrintout = new QPushButton("View Printout");
    connect(viewPrintout, SIGNAL(clicked()), this, SLOT(viewPrintoutClicked()));

    QSpacerItem *spacer = new QSpacerItem(0, 100);

    QPalette palette;
    palette.setBrush(QPalette::Light, Qt::darkGray);

    QVBoxLayout *playbackLayout = new QVBoxLayout;
    playbackLayout->addSpacerItem(spacer);
    playbackLayout->addWidget(bar);
    playbackLayout->addWidget(viewVideo);
    playbackLayout->addWidget(viewPrintout);
    playbackLayout->addSpacerItem(spacer);

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(table);
    mainLayout->addLayout(playbackLayout);

    QWidget *widget = new QWidget;
    widget->setLayout(mainLayout);

    setCentralWidget(widget);
    setWindowTitle("GJJTrainer");
}

void MainWindow::playPosition()
{
    wasPosition = true;
    QDir audioFileDir(techniqueList[currentTechIndex]);
    audioFileDir.cdUp(); //cdup from file to actual directory

    QStringList filters;
    filters << "p_*.wav";
    audioFileDir.setNameFilters(filters);
    mediaObject->setCurrentSource(audioFileDir.path() + "/" + audioFileDir.entryList()[0]);
    mediaObject->play();
}

/************************************************************************************
                                    SLOTS
************************************************************************************/

void MainWindow::play()
{
    if(!wasPosition)
    {
        table->setCurrentCell(currentTechIndex, 0);
        playPosition();
    }
}

//pause is only hit after an audio file has finished playing (not dependent on user input)
void MainWindow::paused()
{
    if(wasPosition)
        timer->start(5000);
    else
        timer->start(10000);
}

//user pressed "pause" button **OR** "view video/printout" pressed
void MainWindow::stop()
{
    if(timer->isActive())
        timer->stop();

    wasPosition = false; //allows playback to continue at position audio
    mediaObject->stop();
}

void MainWindow::next()
{
    stop();
    if(currentTechIndex < techniqueList.size() - 1)
        mediaObject->setCurrentSource(Phonon::MediaSource(techniqueList[++currentTechIndex]));

    //funky workaround for having audio not play after clicking next/previous
    //and also sets the selected table cell
    play();
    stop();
}

void MainWindow::previous()
{
    stop();
    if(currentTechIndex > 0)
        mediaObject->setCurrentSource(Phonon::MediaSource(techniqueList[--currentTechIndex]));
    play();
    stop();
}

void MainWindow::timeOut()
{
    timer->stop();

    if(!(currentTechIndex < techniqueList.size()))
    {
        qDebug() << "Training finished!";
        exit(0);
    }
    else if(wasPosition)
    {
        wasPosition = false;
        mediaObject->setCurrentSource(Phonon::MediaSource(techniqueList[currentTechIndex]));
        mediaObject->play();
    }
    else
    {
        mediaObject->setCurrentSource(Phonon::MediaSource(techniqueList[++currentTechIndex]));
        play();
    }
}

//TODO:need to implelment specific naming conventions for files
void MainWindow::viewPrintoutClicked()
{
    stop();
    qDebug() << "in viewprintoutclicked()";
    QDir dir("printouts/");

    QDirIterator it(dir.path());
    QString fileNameStr = techniqueList[currentTechIndex].section('/', -1).section('.',0,0);
    fileNameStr.truncate(fileNameStr.size() - 1);

    while(it.hasNext())
    {
        qDebug() << "printout it: " << it.fileName();
        if(it.fileName().contains(fileNameStr))
            break;

        it.next();
    }
    QDesktopServices::openUrl(it.filePath());
}

void MainWindow::viewVideoClicked()
{
    stop();

    QDialog *videoDialog = new QDialog();
    videoDialog->setModal(true);
    videoDialog->setMinimumSize(800, 600);

    videoPlayer = new Phonon::VideoPlayer(Phonon::VideoCategory, this);
    connect(videoPlayer, SIGNAL(finished()), this, SLOT(videoReplay()));

    QHBoxLayout *videoLayout = new QHBoxLayout();
    videoLayout->addWidget(videoPlayer);
    videoDialog->setLayout(videoLayout);

    videoFileName = ("video/" + techniqueList[currentTechIndex].section('/', -1).section('.',0,0) + ".avi");

    if(QFile().exists(videoFileName))
    {
        videoPlayer->load(Phonon::MediaSource(videoFileName));
        videoPlayer->play();
        videoDialog->show();
    }
    else
        qDebug() << "file does not exist!";
}

void MainWindow::videoReplay()
{
    videoPlayer->play(Phonon::MediaSource(videoFileName));
}

void MainWindow::stateChanged(Phonon::State newState, Phonon::State /*old state*/)
{
    switch (newState) {
        case Phonon::ErrorState:
            if (mediaObject->errorType() == Phonon::FatalError) {
                QMessageBox::warning(this, tr("Fatal Error"),
                mediaObject->errorString());
            } else {
                QMessageBox::warning(this, tr("Error"),
                mediaObject->errorString());
            }
            break;
        case Phonon::PlayingState:
                qDebug() << QTime().currentTime() << ": playing";
                playAction->setEnabled(false);
                pauseAction->setEnabled(true);
                break;
        case Phonon::StoppedState:
                qDebug() << QTime().currentTime() << ": training paused";
                pauseAction->setEnabled(false);
                playAction->setEnabled(true);
                break;
        case Phonon::PausedState:
                qDebug() << QTime().currentTime() << ": transition";
                paused();
                break;
        case Phonon::BufferingState:
                qDebug() << QTime().currentTime() << ": buffering";
                break;
        default:
            ;
    }
}
